#include<iostream>
using namespace std;
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<assert.h>

void PrintSig(sigset_t& pending)
{
    for(int signo = 31;signo>0;signo--)
    {
        if(sigismember(&pending, signo))
            cout<<"1";
        else
            cout<<"0";
    }
    cout<<endl;
}

void handler(int signo)
{
    sigset_t pending;
    sigemptyset(&pending);
    int n = sigpending(&pending);
    assert(n==0);
    cout<<"递达中...."<<endl;
    PrintSig(pending);
    cout<<"信号signo:"<<signo<<"被递达处理"<<endl;  //递达之前，pending 2号已经被清0
}

int main()
{
    signal(2, handler);
    //1. 屏蔽2号信号
    sigset_t block, o_block;
    sigemptyset(&block);
    sigemptyset(&o_block);
    sigaddset(&block, 2);
    //sigaddset(&block, 9);
    //屏蔽所有信号
    // for(int signo = 1;signo<=31;signo++)     //9, 19无法屏蔽，18号会特殊处理
    //     sigaddset(&block, signo);
    //以上都是栈中操作，并没有设置进内核
    //2. 开始设置进内核
    int n = sigprocmask(SIG_SETMASK, &block, &o_block);
    assert(n==0);
    (void)n;    //因为assert条件编译在release版本，会不存在，为了不告警，假装使用过n
    cout<<"block 2 signo success"<<endl;
    cout<<"pid:"<<getpid()<<endl;
    //3. 获取pending表，查看哪些信号能够被屏蔽哪些不能够被屏蔽
    int cnt = 0;
    while(true)
    {
        sigset_t pending;
        sigemptyset(&pending);
        int n = sigpending(&pending);
        assert(n==0);
        PrintSig(pending);
        cnt++;
        if(cnt == 20)
        {
            cout<<"解除2号信号的屏蔽"<<endl;
            int n = sigprocmask(SIG_UNBLOCK, &block, &o_block);
            assert(n==0);
        }
        sleep(2);   //解除屏蔽后，立即开始对2号信号递达处理
    }
    return 0;
}

// int main()
// {
//     pid_t id = fork();
//     if(id == 0)
//     {
//         //child
//         sleep(2);
//         int a = 10;
//         a/=0;  //除0异常，崩溃      //SIGFPE -> 8
//         exit(0);
//     }
//     //father
//     int status = 0;
//     pid_t rid = waitpid(id, &status, 0);
//     if(rid > 0)
//     {
//         cout<<"exit status:"<<((status>>8)&0xFF)<<endl; //异常退出，不关心结果
//         cout<<"exit signo:"<<(status&0x7F)<<endl;   
//         cout<<"core dump:"<<((status>>7)&0x1)<<endl;
//     }

//     return 0;
// }